package com.ruoyi.flow.common.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
/**
 * properties解析工具类
 * 
 * @author wtian 2015-6-9
 * 
 */
public class PropertiesUtils {
    private static final Log LOGGER = LogFactory.getLog(PropertiesUtils.class);
    private Properties properties;
    private File file;

    private PropertiesUtils(File file) {
        loadProperties(file);
    }

    public static PropertiesUtils load(File propertyFile){
        checkNotNull(propertyFile);
        checkState(propertyFile.exists(),"property file not exist.");
        return new PropertiesUtils(propertyFile);
    }

    public static PropertiesUtils load(String filePath){
        checkNotNull(filePath);
        return load(new File(filePath));
    }

    /**
     * 加载
     * 
     * @param file
     */
    private void loadProperties(File file) {
        if (file == null || !file.exists()) {
            LOGGER.error("Property file is null.", new FileNotFoundException("Property file is null."));
        }
        FileReader reader = null;
        try {
            this.file = file;
            reader = new FileReader(file);
            properties = new Properties();
            properties.load(reader);
        } catch (FileNotFoundException e) {
            LOGGER.error(file.getPath() + " file is not exist!", e);
        } catch (IOException e) {
            LOGGER.error(file.getPath() + " file read happen error.", e);
        } finally {
            closeReader(reader);
        }
    }

    private void closeReader(FileReader reader) {
        IOUtils.closeQuietly(reader);
    }

    /**
     * 获取字符串值
     * 
     * @param key
     * @param defaultValue
     * @return
     */
    public String getString(String key, String defaultValue) {
        String i = properties.getProperty(key, defaultValue);
        return i;
    }

    /**
     * 获取int数值
     * 
     * @param key
     * @param defaultValue
     * @return
     */
    public int getInt(String key, int defaultValue) {
        Integer i = null;
        try {
            i = Integer.parseInt(properties.getProperty(key, String.valueOf(defaultValue)));
        } catch (NumberFormatException e) {
        	LOGGER.error("Error!", e);
        }
        return i;
    }

    /**
     * 获取long数值
     * 
     * @param key
     * @param defaultValue
     * @return
     */
    public long getLong(String key, long defaultValue) {
        Long i = null;
        try {
            i = Long.parseLong(properties.getProperty(key, String.valueOf(defaultValue)));
        } catch (NumberFormatException e) {
        	LOGGER.error("Error!", e);
        }
        return i;
    }

    /**
     * 获取boolean类型值
     * 
     * @param key
     * @param defaultValue
     * @return
     */
    public boolean getBoolean(String key, boolean defaultValue) {
        Boolean i = false;
        try {
            i = Boolean.parseBoolean(properties.getProperty(key, String.valueOf(defaultValue)));
        } catch (Exception e) {
        	LOGGER.error("Error!", e);
        }
        return i;
    }

    /**
     * Get double type value.
     * 
     * @param key
     * @param defaultValue
     * @return
     */

    public double getDouble(String key, double defaultValue) {
        Double i = null;
        try {
            i = Double.parseDouble(properties.getProperty(key, String.valueOf(defaultValue)));
        } catch (NumberFormatException e) {
        	LOGGER.error("Error!", e);
        }
        return i;
    }

    /**
     * 获取对象
     * 
     * @param key
     * @param defaultValue
     * @return
     */
    public <T> T getObject(String key, Class<T> defaultValue) {
        try {
            String className = properties.getProperty(key);
            Class<T> clazz = null;
            if (StringUtils.isEmpty(className)) {
                clazz = defaultValue;
            } else {
                clazz = (Class<T>) Class.forName(className);
            }
            return (T) clazz.newInstance();
        } catch (ClassNotFoundException e) {
        	LOGGER.error("Error!", e);
        } catch (InstantiationException e) {
        	LOGGER.error("Error!", e);
        } catch (IllegalAccessException e) {
        	LOGGER.error("Error!", e);
        }
        return null;
    }

    /**
     * get {@code Properties} object
     * 
     * @return {@code Properties}
     * @see Properties
     */
    public Properties getProperties() {
        return this.properties;
    }

    /**
     * get properties file <code>File</code> object
     * 
     * @return {@code File}
     */
    public File getFile() {
        return this.file;
    }

    @Override
    public String toString() {
        StringBuffer buffer = new StringBuffer(this.file.getName()).append("{");
        Set<Entry<Object, Object>> entrys = this.properties.entrySet();
        Iterator<Entry<Object, Object>> it = entrys.iterator();
        while (it.hasNext()) {
            Entry<Object, Object> entry = it.next();
            buffer.append(entry.getKey()).append("=").append(entry.getValue()).append(",");
        }
        buffer.append("}");
        return buffer.toString();
    }

    public static void main(String[] args) {
        PropertiesUtils pu = PropertiesUtils.load(PropertiesUtils.class.getResource("/").getPath() + "druid.properties");
        System.out.println(pu.toString());
    }

}
